'''
Created on Jul 22, 2011

@author: bstar
'''
from zope.interface import implements
from lxml import etree
from twisted.plugin import IPlugin
import os
import logging
import traceback
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
import markdown2
from dopplershift.collector.renderers.default import IDSCollectorRenderer
from dopplershift.core.plugins.interfaces import IDSPlugin
from dopplershift.collector.renderers.default import DefaultRenderer
import json
from jinja2.exceptions import TemplateSyntaxError
import StringIO
from dopplershift.collector.exc import HttpCustom
from dopplershift.core.utils.jsonserializer import dumps
logger = logging.getLogger(__name__)

class Jinja2Renderer(DefaultRenderer):
    name = "jinja2"
    default_content_type = 'application/json'
    implements(IPlugin, IDSPlugin, IDSCollectorRenderer)
    def configure(self, config):
        self.env = Environment(loader=FileSystemLoader(config.get_templates_path()), extensions=['jinja2.ext.with_'])
        self.env.filters['markdown'] = markdown2.markdown
        self.loadFilters(config)
        self.flat_context = False
        if config.get("jinja.flat_context") == 'True':
            self.flat_context = True
        DefaultRenderer.configure(self, config)
    def loadFilters(self, config):
        for k,v in config.get_list(key="jinja.filters_loader"):
            module, func = v.split(":")
            mf=".".join(module.split('.')[:-1])
            filters_dict = getattr(__import__(module, fromlist=[mf]), func)()
            self.env.filters.update(filters_dict)
            
    def getTemplate(self, template_name):
        try:
            tmpl = self.env.get_template(template_name)
            self._templates[template_name] = tmpl
            return tmpl
        except TemplateNotFound:
            print "[ERROR] File not found", template_name
        except TemplateSyntaxError:
            print "[ERROR] File content error and template not loaded", template_name
            traceback.print_exc()
            
    def rendering(self, request, data, template_name, content_type):
        result = ''
        if template_name is None:
            
            result = dumps(data)
        else:
            tmpl = self.getTemplate(template_name)
            if tmpl is None:
                self.error_render(request, 500)
                return 
            try:
                result = tmpl.render(data)
            except:
                errf = StringIO.StringIO()
                traceback.print_exc(file=errf)
                errf.seek(0)
                result = "<pre>%s AAAAA</pre>"%str(errf.read())
        request.setHeader('Content-Type', content_type)
        request.write(str(result.encode("utf-8"))) 
        #request.write(str(result)) 
        request.finish()
    def prepare(self, data, calls_idents, matched_params, auth_user, as_string=True, request=None):
        
        material = {}
        session = {}
        redirect = None
        result = {
                  'material': material,
                  'session': session
                  }
        for el in calls_idents:
            err_excp = el.getExcepting()
            node_id = el.getNodeName()
            if node_id not in data and 404 in err_excp:
                return self.renderInternalServerError() 
            
            current = self.prepare_json_data(data[node_id].body, as_string=True)
            if int(data[node_id].code) != 200:
                raise HttpCustom(int(data[node_id].code))
            if current == None:
                material[node_id] = None
            elif 'content' in current:
                if self.flat_context: material.update(current['content'])
                else: material[node_id] = current['content']
            res = self.session(current)
            session.update(res)
            if redirect is None:
                redirect = self.redirect(current)
        if not redirect is None:
            result['redirect'] = redirect 
        material['matched_params'] = matched_params
        material['auth_user'] = auth_user
        if request is not None:
            material['request'] = request.args
        if not request is None:
            material['url'] = request.current_url
        return result
    def session(self, data):
        session = {}
        if data is not None and 'session' in data :
            for key,value in data['session'].iteritems():
                session[key] = value
                
        return session
    def redirect(self, data):
        if data is not None and 'redirect' in data:
            return data['redirect']
    def prepare_json_data(self, data, as_string=True):
        try:
            return json.loads(data)
        except:
            pass
    def error_render(self, request, code, as_string=False):
        request.setResponseCode(code)
        tmpl = self._prerendered_errors.get(str(code))
        r = str(tmpl.render())
        if as_string==True:
            return r
        request.write(r)
        request.finish()
        return